package Simulation;

import java.util.ArrayList;
import Config.Config;

import People.Animal;
import People.People;
import People.Person;
import People.Status;

/**
 * Models the map of simulation
 * 
 * @author Amir BEN SLIMANE
 */
public class Map extends Manager {
	private People[][] mapSimulation;
	private int infected;
	private ArrayList<People> peopleList;

	/**
	 * Builder's Map
	 * 
	 * @param infected
	 */
	public Map(int infected) {
		this.peopleList = new ArrayList<>();
		this.mapSimulation = new People[Config.MAP_HEIGTH][Config.MAP_LENGTH];
		this.infected = infected;
	}

	/**
	 * Initializes people in the map and random placing 
	 */
	public void intitializePeople() {
		boolean vaccin;
		try {
			for (int i = 0; i < Config.PERSON_POPULATION - this.infected; i++) {
				vaccin = ((int) (Math.random() * 101) < Config.VACCINATED_RATE) ? false : true;
				peopleList.add(new Person(Status.Healthy, vaccin, (int) Math
						.random() * 20));
			}

			for (int i = 0; i < this.infected; i++) {
				if((int) (Math.random() * 2) == 0){
					vaccin = ((int) (Math.random() * 101) < Config.VACCINATED_RATE) ? false : true;
					peopleList.add(new Person(Status.Sick, vaccin, (int) Math
							.random() * 20));
				}else{
					vaccin = ((int) (Math.random() * 101) < Config.VACCINATED_RATE) ? false : true;
					peopleList.add(new Animal(Status.Sick, vaccin));
				}
			}

			for (int i = 0; i < Config.ANIMAL_POPULATION; i++) {
				vaccin = ((int) (Math.random() * 101) < Config.VACCINATED_RATE) ? false : true;
				peopleList.add(new Animal(Status.Healthy, vaccin));
			}

		} catch (Exception e) {
			System.out.println("Insufficient size map for this population !");
		}
		putPeopleRandom();
	}

	/**
	 * Place in order the people
	 */
	private void putPeople() {
		for (int i = 0; i < Config.MAP_HEIGTH * Config.MAP_LENGTH; i++) {
			if (i < this.peopleList.size()) {
				if (i / Config.MAP_LENGTH >= Config.MAP_HEIGTH) {
					break;
				}
				this.mapSimulation[i / Config.MAP_LENGTH][i % Config.MAP_LENGTH] = this.peopleList
						.get(i);
			} else {
				this.mapSimulation[i / Config.MAP_LENGTH][i % Config.MAP_LENGTH] = new People(
						Status.Empty);
			}

		}

	}

	/**
	 * Randomize the people
	 */
	private void putPeopleRandom() {
		putPeople();
		for (int cpt = 0; cpt < Config.MIX_ITERATE; cpt++) {
			switchPeople(
					this.mapSimulation[(int) (Math.random() * Config.MAP_HEIGTH)][(int) (Math
							.random() * Config.MAP_LENGTH)],
					this.mapSimulation[(int) (Math.random() * Config.MAP_HEIGTH)][(int) (Math
							.random() * Config.MAP_LENGTH)]);
		}
	}

	/**
	 * @return the map
	 */
	public People[][] getMapSimulation() {
		return mapSimulation;
	}

	/**
	 * Displays the map
	 */
	public String toString() {
		String map = "";

		for (int i = 0; i < Config.MAP_HEIGTH; i++) {
			if (Config.MAP_HEIGTH > 10 && i >= 10) {
				map += i + ":| ";
			} else {
				map += i + " :| ";
			}
			for (int j = 0; j < Config.MAP_LENGTH; j++) {
				if (this.mapSimulation[i][j].getStatus() != Status.Empty) {
					if (this.mapSimulation[i][j].getClass() == Animal.class) {
						map += "A";
					} else {
						map += "P";
					}
					map += this.mapSimulation[i][j].toString() + " | ";
				} else {
					map += this.mapSimulation[i][j].toString() + "  | ";
				}
			}
			map += "\n";
		}

		return map;
	}
}
